<?php

class QQAPI
{
    /**
     * QQ登录class
     * link http://www.scphp.com
     * Author MrHan(hcj112@163.com)
     * 2013-8-24
     * @var type 
     */
    
    
    protected $appId = NULL;
    protected $appKey = NULL;
    protected $callback = NULL;
    protected $keysArr = array();
    const AUTH_CODE_URL = 'https://graph.qq.com/oauth2.0/authorize';
    const ACCESS_TOKEN_URL = 'https://graph.qq.com/oauth2.0/token';
    const OPENID_URL = 'https://graph.qq.com/oauth2.0/me';
    const USER_INFO_URL = 'https://graph.qq.com/user/get_user_info';
    const SCOPE = 'get_user_info';
    
    
    //构造函数初使化
    public function __construct($appId,$appKey,$callback)
    {
        $this->appId = $appId;
        $this->appKey = $appKey;
        $this->callback = $callback;
    }
    
    //QQ登录
    public function login()
    {
        //生成唯一随便串防止CSRF攻击
        $_SESSION[C('SES_STATE_NAME')] = md5(uniqid(rand(), TRUE));
        
        $keysArr = array(
            'response_type' => 'code',
            'client_id' => $this->appId,
            'redirect_uri' => $this->callback,
            'scope' => self::SCOPE,
            'state' => $_SESSION[C('SES_STATE_NAME')],
        );
        //格式化URL
        $loginUrl = self::AUTH_CODE_URL.'?'.http_build_query($keysArr);
        
        header("Location:$loginUrl");
    }
    
    /**
     * 
     * QQ登录成功后的回调函数
     */
    public function callback()
    {
        $state = $_GET['state'];
        if($state != $_SESSION[C('SES_STATE_NAME')])
            throw_exception('The state does not match. You may be a victim of CSRF.');
        
        $keysArr = array(
             'grant_type' => 'authorization_code',
             'client_id' => $this->appId,
             'redirect_uri' => $this->callback,
             'client_secret' => $this->appKey,
             'code' => $_GET ["code"],
            );
        $tokenUrl = self::ACCESS_TOKEN_URL.'?'.http_build_query($keysArr);
        $response = self::get_url_contents($tokenUrl);
        
        if (strpos($response, "callback") !== FALSE) {
                $lpos = strpos($response, "(");
                $rpos = strrpos($response, ")");
                $response = substr($response, $lpos + 1, $rpos - $lpos - 1);
                $msg = json_decode($response);
                if (isset($msg->error)) {
                    echo "<h3>错误代码:</h3>" . $msg->error;
                    echo "<h3>信息  :</h3>" . $msg->error_description;
                    exit();
                }
            }

            $params = array();
            parse_str($response, $params);
            $_SESSION [C('SES_TOKEN_NAME')] = $params ["access_token"];            
    }
    
    /**
     * 
     * get获取QQ的openid,每个QQ对就一个唯一的openid
     */
    public function getOpenId()
    {
        $keysArr = array(
            'access_token' => $_SESSION [C('SES_TOKEN_NAME')]
        );
        $graph_url = self::OPENID_URL .'?'. http_build_query($keysArr);
        $str = self::get_url_contents($graph_url);
        
        if (strpos($str, "callback") !== false) {
            $lpos = strpos($str, "(");
            $rpos = strrpos($str, ")");
            $str = substr($str, $lpos + 1, $rpos - $lpos - 1);
        }

        $user = json_decode($str);
        if (isset($user->error)) {
            echo "<h3>错误代码:</h3>" . $user->error;
            echo "<h3>信息  :</h3>" . $user->error_description;
            exit();
        }
        
        $_SESSION [C('SES_OPENID_NAME')] = $user->openid;
    }
    
    
    
    /**
     * 
     * get获取用户信息
     * @return type string 
     */
    public function get_user_info()
    {
        $keysArr = array(
            'access_token' => $_SESSION [C('SES_TOKEN_NAME')],
            'oauth_consumer_key' => C('app_id'),
            'openid' => $_SESSION [C('SES_OPENID_NAME')],
            'format' => 'json',
        );
        $get_user_info = self::USER_INFO_URL . '?' . http_build_query($keysArr);
        
        return self::get_url_contents($get_user_info);
    }

    /**
     * get_url_contents
     * 服务器通过get请求获得内容
     * @param string $url   请求的url,拼接后的
     * @return string  $response    请求返回的内容
     */
    static private function get_url_contents($url)
    {
        if (ini_get("allow_url_fopen") == "1") {
            $response = file_get_contents($url);
        } else {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($ch, CURLOPT_URL, $url);
            $response = curl_exec($ch);
            curl_close($ch);
       }

        //请求为空
        if (empty($response)) {
            throw_exception('可能是服务器无法请求https协议</h2>可能未开启curl支持,请尝试开启curl支持，重启web服务器，如果问题仍未解决，请联系我们');
        }

        return $response;
    }
}
?>